#include<iostream>
#include<thread>

int a = 0;
void func()
{
	for (int i = 0; i < 10000; i++)
	{
		a += 1;
	}
}

int main()
{
	std::thread t1(func);
	std::thread t2(func);

	t1.join();
	t2.join();

	std::cout << a << std::endl;	//结果不是20000，因为缺少互斥量，t1和t2可能同时取到a
						//如果a=0，t1和t2同时取到a，t1：a=a+1=1， t2：a=a+1=1 最终a=1并不等于2
	return 0;
}







//用互斥锁解决该问题，不允许t1和t2同时访问a
#include<iostream>
#include<thread>
#include<mutex>		//互斥锁头文件

int a = 0;
std::mutex mtx;		//创建一个互斥锁
void func()
{
	for (int i = 0; i < 10000; i++)
	{
		mtx.lock();	//上锁
		a += 1;
		mtx.unlock(); // 解锁
	}
}

int main()
{
	std::thread t1(func);
	std::thread t2(func);

	t1.join();
	t2.join();

	std::cout << a << std::endl;		//结果为20000

	return 0;
}







//死锁
//产生条件: 1.互斥条件(避免死锁时不能破坏此条件，其余都可)  2.不剥夺条件  3.环路等待条件  4.请求和保持条件
#include<iostream>
#include<thread>
#include<mutex>

std::mutex m1, m2;

void func_1()
{
	for (int i = 0; i < 500; i++)
	{
		m1.lock();
		m2.lock();
		
		m1.unlock();
		m2.unlock();
	}
	
}

void func_2()
{
	for(int i=0; i<500; i++)
	{
		m2.lock();  //t1获取到m1后t2获取到m2，两方都无法获取两个m，造成死锁
		m1.lock();

		m2.unlock();
		m1.unlock();
	}
}

int main()
{
	std::thread t1(func_1);
	std::thread t2(func_2);

	t1.join();
	t2.join();
	std::cout << "over" << std::endl;	//造成死锁，无法打印over
	return 0;
}






//解决办法
#include<iostream>
#include<thread>
#include<mutex>

std::mutex m1, m2;

void func_1()
{
	for (int i = 0; i < 500; i++)
	{
		m1.lock();
		m2.lock();
		
		m1.unlock();
		m2.unlock();
	}
	
}

void func_2()
{
	for(int i=0; i<500; i++)
	{
		m1.lock();      //交换顺序，同时对m1进行上锁，假如t1拿到，t2连m1都没拿到就不会去抢m2
		m2.lock();

		m2.unlock();
		m1.unlock();
	}
}

int main()
{
	std::thread t1(func_1);
	std::thread t2(func_2);

	t1.join();
	t2.join();
	std::cout << "over" << std::endl;	//避免了死锁，打印over  此为破坏环路条件
	return 0;
}